package de.siegmar.fastcsv.reader;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;

/// Index built by [IndexedCsvReader] to access large CSV data files.
///
/// Even if the constructor is public (mandatory for record classes),
/// this class is **not intended to be instantiated directly!**
///
/// @param bomHeaderLength  The length of an optional BOM header.
/// @param fileSize         The CSV file size this index was built for.
/// @param fieldSeparator   The field separator used when building this index.
/// @param quoteCharacter   The quote character used when building this index.
/// @param commentStrategy  The comment strategy used when building this index.
/// @param commentCharacter The comment character used when building this index.
/// @param recordCount      The total number of records the CSV file contains this index was built for.
/// @param pages            The pages this index is partitioned.
public class CsvIndex implements Serializable {
    private int bomHeaderLength;
    private long fileSize;
    private byte fieldSeparator;
    private byte quoteCharacter;
    private CommentStrategy commentStrategy;
    private byte commentCharacter;
    private long recordCount;
    private List<CsvPage> pages;

    /// Constructor for the [CsvIndex] class.
    ///
    /// @throws NullPointerException if the `commentStrategy` or `pages` is `null`
    @SuppressWarnings("checkstyle:ParameterNumber")
    public CsvIndex(final int bomHeaderLength, final long fileSize, final byte fieldSeparator,
                    final byte quoteCharacter, final CommentStrategy commentStrategy, final byte commentCharacter,
                    final long recordCount, final List<CsvPage> pages) {
        this.bomHeaderLength = bomHeaderLength;
        this.fileSize = fileSize;
        this.fieldSeparator = fieldSeparator;
        this.quoteCharacter = quoteCharacter;
        this.commentStrategy = Objects.requireNonNull(commentStrategy, "commentStrategy must not be null");
        this.commentCharacter = commentCharacter;
        this.recordCount = recordCount;
        this.pages = Objects.requireNonNull(pages, "pages must not be null");
    }

    /// {@return string representation of this index without the pages themselves}
    @Override
    public String toString() {
        return new StringJoiner(", ", CsvIndex.class.getSimpleName() + "[", "]")
            .add("bomHeaderLength=" + bomHeaderLength)
            .add("fileSize=" + fileSize)
            .add("fieldSeparator=" + fieldSeparator)
            .add("quoteCharacter=" + quoteCharacter)
            .add("commentStrategy=" + commentStrategy)
            .add("commentCharacter=" + commentCharacter)
            .add("recordCount=" + recordCount)
            .add("pageCount=" + pages.size())
            .toString();
    }

    public int getBomHeaderLength() {
        return bomHeaderLength;
    }
    public void setBomHeaderLength(int bomHeaderLength) {
        this.bomHeaderLength = bomHeaderLength;
    }
    public byte getCommentCharacter() {
        return commentCharacter;
    }
    public void setCommentCharacter(byte commentCharacter) {
        this.commentCharacter = commentCharacter;
    }
    public CommentStrategy getCommentStrategy() {
        return commentStrategy;
    }
    public void setCommentStrategy(CommentStrategy commentStrategy) {
        this.commentStrategy = commentStrategy;
    }
    public byte getFieldSeparator() {
        return fieldSeparator;
    }
    public void setFieldSeparator(byte fieldSeparator) {
        this.fieldSeparator = fieldSeparator;
    }
    public long getFileSize() {
        return fileSize;
    }
    public void setFileSize(long fileSize) {
        this.fileSize = fileSize;
    }
    public List<CsvPage> getPages() {
        return pages;
    }
    public void setPages(List<CsvPage> pages) {
        this.pages = pages;
    }
    public byte getQuoteCharacter() {
        return quoteCharacter;
    }
    public void setQuoteCharacter(byte quoteCharacter) {
        this.quoteCharacter = quoteCharacter;
    }
    public long getRecordCount() {
        return recordCount;
    }
    public void setRecordCount(long recordCount) {
        this.recordCount = recordCount;
    }

    /// Represents a page of the CSV file.
    ///
    /// @param offset             The offset of the page in the CSV file.
    /// @param startingLineNumber The starting line number of the page.
    public static class CsvPage implements Serializable {
        private long offset;
        private long startingLineNumber;
        public CsvPage(long offset, long startingLineNumber){
            this.offset = offset;
            this.startingLineNumber = startingLineNumber;
        }

        public long getOffset() {
            return offset;
        }

        public void setOffset(long offset) {
            this.offset = offset;
        }

        public long getStartingLineNumber() {
            return startingLineNumber;
        }

        public void setStartingLineNumber(long startingLineNumber) {
            this.startingLineNumber = startingLineNumber;
        }
    }

}
